From f7382221cdb895ec836a1b9a629f84ad42ecb3eb Mon Sep 17 00:00:00 2001 From: Jonathan Blandford Date: Wed, 28 Feb 2001 21:37:50 +0000 Subject: [PATCH] Sanitize GtkRowReference. Wed Feb 28 16:36:46 2001 Jonathan Blandford * gtk/gtktreemodel.c (gtk_tree_row_reference_*): Sanitize GtkRowReference. --- ChangeLog | 5 + ChangeLog.pre-2-0 | 5 + ChangeLog.pre-2-10 | 5 + ChangeLog.pre-2-2 | 5 + ChangeLog.pre-2-4 | 5 + ChangeLog.pre-2-6 | 5 + ChangeLog.pre-2-8 | 5 + gtk/gtktreemodel.c | 747 +++++++++++++++++++++-------------------- gtk/gtktreemodel.h | 119 ++++--- gtk/gtktreeprivate.h | 8 +- gtk/gtktreeselection.c | 91 +++-- gtk/gtktreeview.c | 22 +- 12 files changed, 537 insertions(+), 485 deletions(-) diff --git a/ChangeLog b/ChangeLog index f4dae8b51a..78288d7680 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +Wed Feb 28 16:36:46 2001 Jonathan Blandford + + * gtk/gtktreemodel.c (gtk_tree_row_reference_*): Sanitize + GtkRowReference. + 2001-02-28 Havoc Pennington * gtk/gtkwidget.h (struct _GtkWidgetClass): Remove draw_focus and diff --git a/ChangeLog.pre-2-0 b/ChangeLog.pre-2-0 index f4dae8b51a..78288d7680 100644 --- a/ChangeLog.pre-2-0 +++ b/ChangeLog.pre-2-0 @@ -1,3 +1,8 @@ +Wed Feb 28 16:36:46 2001 Jonathan Blandford + + * gtk/gtktreemodel.c (gtk_tree_row_reference_*): Sanitize + GtkRowReference. + 2001-02-28 Havoc Pennington * gtk/gtkwidget.h (struct _GtkWidgetClass): Remove draw_focus and diff --git a/ChangeLog.pre-2-10 b/ChangeLog.pre-2-10 index f4dae8b51a..78288d7680 100644 --- a/ChangeLog.pre-2-10 +++ b/ChangeLog.pre-2-10 @@ -1,3 +1,8 @@ +Wed Feb 28 16:36:46 2001 Jonathan Blandford + + * gtk/gtktreemodel.c (gtk_tree_row_reference_*): Sanitize + GtkRowReference. + 2001-02-28 Havoc Pennington * gtk/gtkwidget.h (struct _GtkWidgetClass): Remove draw_focus and diff --git a/ChangeLog.pre-2-2 b/ChangeLog.pre-2-2 index f4dae8b51a..78288d7680 100644 --- a/ChangeLog.pre-2-2 +++ b/ChangeLog.pre-2-2 @@ -1,3 +1,8 @@ +Wed Feb 28 16:36:46 2001 Jonathan Blandford + + * gtk/gtktreemodel.c (gtk_tree_row_reference_*): Sanitize + GtkRowReference. + 2001-02-28 Havoc Pennington * gtk/gtkwidget.h (struct _GtkWidgetClass): Remove draw_focus and diff --git a/ChangeLog.pre-2-4 b/ChangeLog.pre-2-4 index f4dae8b51a..78288d7680 100644 --- a/ChangeLog.pre-2-4 +++ b/ChangeLog.pre-2-4 @@ -1,3 +1,8 @@ +Wed Feb 28 16:36:46 2001 Jonathan Blandford + + * gtk/gtktreemodel.c (gtk_tree_row_reference_*): Sanitize + GtkRowReference. + 2001-02-28 Havoc Pennington * gtk/gtkwidget.h (struct _GtkWidgetClass): Remove draw_focus and diff --git a/ChangeLog.pre-2-6 b/ChangeLog.pre-2-6 index f4dae8b51a..78288d7680 100644 --- a/ChangeLog.pre-2-6 +++ b/ChangeLog.pre-2-6 @@ -1,3 +1,8 @@ +Wed Feb 28 16:36:46 2001 Jonathan Blandford + + * gtk/gtktreemodel.c (gtk_tree_row_reference_*): Sanitize + GtkRowReference. + 2001-02-28 Havoc Pennington * gtk/gtkwidget.h (struct _GtkWidgetClass): Remove draw_focus and diff --git a/ChangeLog.pre-2-8 b/ChangeLog.pre-2-8 index f4dae8b51a..78288d7680 100644 --- a/ChangeLog.pre-2-8 +++ b/ChangeLog.pre-2-8 @@ -1,3 +1,8 @@ +Wed Feb 28 16:36:46 2001 Jonathan Blandford + + * gtk/gtktreemodel.c (gtk_tree_row_reference_*): Sanitize + GtkRowReference. + 2001-02-28 Havoc Pennington * gtk/gtkwidget.h (struct _GtkWidgetClass): Remove draw_focus and diff --git a/gtk/gtktreemodel.c b/gtk/gtktreemodel.c index aa051f1155..052eddb3c0 100644 --- a/gtk/gtktreemodel.c +++ b/gtk/gtktreemodel.c @@ -25,6 +25,9 @@ #include #include "gtkmarshal.h" #include "gtktreemodel.h" +#include "gtktreeview.h" +#include "gtktreeprivate.h" + struct _GtkTreePath { @@ -110,9 +113,9 @@ gtk_tree_model_base_init (gpointer g_class) /** * gtk_tree_path_new: - * + * * Creates a new #GtkTreePath. - * + * * Return value: A newly created #GtkTreePath. **/ /* GtkTreePath Operations */ @@ -130,13 +133,13 @@ gtk_tree_path_new (void) /** * gtk_tree_path_new_from_string: * @path: The string representation of a path. - * + * * Creates a new #GtkTreePath initialized to @path. @path is expected * to be a colon separated list of numbers. For example, the string * "10:4:0" would create a path of depth 3 pointing to the 11th child * of the root node, the 5th child of that 11th child, and the 1st * child of that 5th child. - * + * * Return value: A newly created #GtkTreePath. **/ GtkTreePath * @@ -167,10 +170,10 @@ gtk_tree_path_new_from_string (gchar *path) /** * gtk_tree_path_to_string: * @path: A #GtkTreePath - * + * * Generates a string representation of the path. This string is a ':' * separated list of numbers. For example, "4:10:0:3" would be an acceptable return value for this string. - * + * * Return value: A newly allocated string. Must be freed with #g_free. **/ gchar * @@ -199,10 +202,10 @@ gtk_tree_path_to_string (GtkTreePath *path) /** * gtk_tree_path_new_root: - * + * * Creates a new root #GtkTreePath. The string representation of this path is * "0" - * + * * Return value: A new #GtkTreePath. **/ GtkTreePath * @@ -220,7 +223,7 @@ gtk_tree_path_new_root (void) * gtk_tree_path_append_index: * @path: A #GtkTreePath. * @index: The index. - * + * * Appends a new index to a path. As a result, the depth of the path is * increased. **/ @@ -240,7 +243,7 @@ gtk_tree_path_append_index (GtkTreePath *path, * gtk_tree_path_prepend_index: * @path: A #GtkTreePath. * @index: The index. - * + * * Prepends a new index to a path. As a result, the depth of the path is * increased. **/ @@ -264,9 +267,9 @@ gtk_tree_path_prepend_index (GtkTreePath *path, /** * gtk_tree_path_get_depth: * @path: A #GtkTreePath. - * + * * Returns the current depth of @path. - * + * * Return value: The depth of @path **/ gint @@ -280,10 +283,10 @@ gtk_tree_path_get_depth (GtkTreePath *path) /** * gtk_tree_path_get_indices: * @path: A #GtkTreePath. - * + * * Returns the current indices of @path. This is an array of integers, each * representing a node in a tree. - * + * * Return value: The current indices, or NULL. **/ gint * @@ -297,7 +300,7 @@ gtk_tree_path_get_indices (GtkTreePath *path) /** * gtk_tree_path_free: * @path: A #GtkTreePath. - * + * * Frees @path. **/ void @@ -312,9 +315,9 @@ gtk_tree_path_free (GtkTreePath *path) /** * gtk_tree_path_copy: * @path: A #GtkTreePath. - * + * * Creates a new #GtkTreePath as a copy of @path. - * + * * Return value: A new #GtkTreePath. **/ GtkTreePath * @@ -335,11 +338,11 @@ gtk_tree_path_copy (GtkTreePath *path) * gtk_tree_path_compare: * @a: A #GtkTreePath. * @b: A #GtkTreePath to compare with. - * + * * Compares two paths. If @a appears before @b in a tree, then 1, is returned. * If @b appears before @a, then -1 is returned. If the two nodes are equal, * then 0 is returned. - * + * * Return value: The relative positions of @a and @b **/ gint @@ -369,9 +372,9 @@ gtk_tree_path_compare (const GtkTreePath *a, * gtk_tree_path_is_ancestor: * @path: a #GtkTreePath * @descendant: another #GtkTreePath - * - * - * + * + * + * * Return value: %TRUE if @descendant is contained inside @path **/ gboolean @@ -379,14 +382,14 @@ gtk_tree_path_is_ancestor (GtkTreePath *path, GtkTreePath *descendant) { gint i; - + g_return_val_if_fail (path != NULL, FALSE); g_return_val_if_fail (descendant != NULL, FALSE); /* can't be an ancestor if we're deeper */ if (path->depth >= descendant->depth) return FALSE; - + i = 0; while (i < path->depth) { @@ -402,9 +405,9 @@ gtk_tree_path_is_ancestor (GtkTreePath *path, * gtk_tree_path_is_descendant: * @path: a #GtkTreePath * @ancestor: another #GtkTreePath - * - * - * + * + * + * * Return value: %TRUE if @ancestor contains @path somewhere below it **/ gboolean @@ -412,14 +415,14 @@ gtk_tree_path_is_descendant (GtkTreePath *path, GtkTreePath *ancestor) { gint i; - + g_return_val_if_fail (path != NULL, FALSE); g_return_val_if_fail (ancestor != NULL, FALSE); - + /* can't be a descendant if we're shallower in the tree */ if (path->depth <= ancestor->depth) return FALSE; - + i = 0; while (i < ancestor->depth) { @@ -435,7 +438,7 @@ gtk_tree_path_is_descendant (GtkTreePath *path, /** * gtk_tree_path_next: * @path: A #GtkTreePath. - * + * * Moves the @path to point to the next node at the current depth. **/ void @@ -450,9 +453,9 @@ gtk_tree_path_next (GtkTreePath *path) /** * gtk_tree_path_prev: * @path: A #GtkTreePath. - * + * * Moves the @path to point to the previous node at the current depth, if it exists. - * + * * Return value: TRUE if @path has a previous node, and the move was made. **/ gboolean @@ -471,9 +474,9 @@ gtk_tree_path_prev (GtkTreePath *path) /** * gtk_tree_path_up: * @path: A #GtkTreePath. - * + * * Moves the @path to point to it's parent node, if it has a parent. - * + * * Return value: TRUE if @path has a parent, and the move was made. **/ gboolean @@ -492,7 +495,7 @@ gtk_tree_path_up (GtkTreePath *path) /** * gtk_tree_path_down: * @path: A #GtkTreePath. - * + * * Moves @path to point to the first child of the current path. **/ void @@ -503,312 +506,15 @@ gtk_tree_path_down (GtkTreePath *path) gtk_tree_path_append_index (path, 0); } -struct _GtkTreeRowReference -{ - GtkTreeModel *model; - GtkTreePath *path; -}; - -typedef struct _RowRefList RowRefList; - -struct _RowRefList -{ - GSList *list; -}; - - -/* - * row_reference - */ -void -_gtk_tree_row_reference_inserted (GtkTreeRowReference *reference, - GtkTreePath *path) -{ - if (reference->path) - { - gint depth = gtk_tree_path_get_depth (path); - gint ref_depth = gtk_tree_path_get_depth (reference->path); - - if (ref_depth >= depth) - { - gint *indices = gtk_tree_path_get_indices (path); - gint *ref_indices = gtk_tree_path_get_indices (reference->path); - gint i; - - /* This is the depth that might affect us. */ - i = depth - 1; - - if (indices[i] <= ref_indices[i]) - ref_indices[i] += 1; - } - } -} - -/* Returns TRUE if the reference path was deleted; FALSE otherwise */ -gboolean -_gtk_tree_row_reference_deleted (GtkTreeRowReference *reference, - GtkTreePath *path) -{ - if (reference->path) - { - gint depth = gtk_tree_path_get_depth (path); - gint ref_depth = gtk_tree_path_get_depth (reference->path); - - if (ref_depth >= depth) - { - /* Need to adjust path upward */ - gint *indices = gtk_tree_path_get_indices (path); - gint *ref_indices = gtk_tree_path_get_indices (reference->path); - gint i; - - i = depth - 1; - if (indices[i] < ref_indices[i]) - ref_indices[i] -= 1; - else if (indices[i] == ref_indices[i]) - { - /* the referenced node itself, or its parent, was - * deleted, mark invalid - */ - - gtk_tree_path_free (reference->path); - reference->path = NULL; - return TRUE; - } - } - } - return FALSE; -} - -static void -release_row_references (gpointer data) -{ - RowRefList *refs = data; - GSList *tmp_list = NULL; - - tmp_list = refs->list; - while (tmp_list != NULL) - { - GtkTreeRowReference *reference = tmp_list->data; - - reference->model = NULL; - - /* we don't free the reference, users are responsible for that. */ - - tmp_list = g_slist_next (tmp_list); - } - - g_slist_free (refs->list); - g_free (refs); -} - -static void -inserted_callback (GtkTreeModel *tree_model, - GtkTreePath *path, - GtkTreeIter *iter, - gpointer data) -{ - RowRefList *refs = data; - GSList *tmp_list; - - /* This function corrects the path stored in the reference to - * account for an insertion. Note that it's called _after_ the insertion - * with the path to the newly-inserted row. Which means that - * the inserted path is in a different "coordinate system" than - * the old path (e.g. if the inserted path was just before the old path, - * then inserted path and old path will be the same, and old path must be - * moved down one). - */ - - tmp_list = refs->list; - - while (tmp_list != NULL) - { - GtkTreeRowReference *reference = tmp_list->data; - - _gtk_tree_row_reference_inserted (reference, path); - - tmp_list = g_slist_next (tmp_list); - } -} - -static void -deleted_callback (GtkTreeModel *tree_model, - GtkTreePath *path, - gpointer data) -{ - RowRefList *refs = data; - GSList *tmp_list; - - /* This function corrects the path stored in the reference to - * account for an deletion. Note that it's called _after_ the - * deletion with the old path of the just-deleted row. Which means - * that the deleted path is the same now-defunct "coordinate system" - * as the path saved in the reference, which is what we want to fix. - * - * Note that this is different from the situation in "inserted," so - * while you might think you can cut-and-paste between these - * functions, it's not going to work. ;-) - */ - - tmp_list = refs->list; - - while (tmp_list != NULL) - { - GtkTreeRowReference *reference = tmp_list->data; - - _gtk_tree_row_reference_deleted (reference, path); - - tmp_list = g_slist_next (tmp_list); - } -} - -static void -connect_ref_callbacks (GtkTreeModel *model, - RowRefList *refs) -{ - g_signal_connect_data (G_OBJECT (model), - "inserted", - (GCallback) inserted_callback, - refs, - NULL, - FALSE, - FALSE); - - g_signal_connect_data (G_OBJECT (model), - "deleted", - (GCallback) deleted_callback, - refs, - NULL, - FALSE, - FALSE); - -#if 0 - /* FIXME */ - g_signal_connect_data (G_OBJECT (model), - "reordered", - (GCallback) reordered_callback, - refs, - NULL, - FALSE, - FALSE); -#endif -} - -static void -disconnect_ref_callbacks (GtkTreeModel *model, - RowRefList *refs) -{ - g_signal_handlers_disconnect_matched (G_OBJECT (model), - G_SIGNAL_MATCH_DATA, - 0, - 0, - NULL, - NULL, - refs); -} - -GtkTreeRowReference* -gtk_tree_row_reference_new (GtkTreeModel *model, - GtkTreePath *path) -{ - GtkTreeRowReference *reference; - RowRefList *refs; - - reference = g_new (GtkTreeRowReference, 1); - - reference->model = model; - reference->path = gtk_tree_path_copy (path); - - refs = g_object_get_data (G_OBJECT (model), - "gtk-tree-row-refs"); - - if (refs == NULL) - { - refs = g_new (RowRefList, 1); - refs->list = NULL; - connect_ref_callbacks (model, refs); - g_object_set_data_full (G_OBJECT (model), - "gtk-tree-row-refs", - refs, - release_row_references); - } - - refs->list = g_slist_prepend (refs->list, reference); - - return reference; -} - -GtkTreeRowReference * -_gtk_tree_row_reference_new_from_view (GtkTreePath *path) -{ - GtkTreeRowReference *reference; - - reference = g_new (GtkTreeRowReference, 1); - - reference->model = NULL; - reference->path = gtk_tree_path_copy (path); - - return reference; -} - -GtkTreePath* -gtk_tree_row_reference_get_path (GtkTreeRowReference *reference) -{ - g_return_val_if_fail (reference != NULL, NULL); - - if (reference->model == NULL) - return NULL; - - if (reference->path == NULL) - return NULL; - - return gtk_tree_path_copy (reference->path); -} - -void -gtk_tree_row_reference_free (GtkTreeRowReference *reference) -{ - RowRefList *refs; - - g_return_if_fail (reference != NULL); - - if (reference->model) - { - refs = g_object_get_data (G_OBJECT (reference->model), - "gtk-tree-row-refs"); - - if (refs == NULL) - { - g_warning (G_STRLOC": bad row reference, model has no outstanding row references"); - return; - } - - refs->list = g_slist_remove (refs->list, reference); - - if (refs->list == NULL) - { - disconnect_ref_callbacks (reference->model, refs); - g_object_set_data (G_OBJECT (reference->model), - "gtk-tree-row-refs", - NULL); - } - } - - if (reference->path) - gtk_tree_path_free (reference->path); - - g_free (reference); -} - /** * gtk_tree_iter_copy: * @iter: A #GtkTreeIter. - * + * * Creates a dynamically allocated tree iterator as a copy of @iter. This * function is not intended for use in applications, because you can just copy * the structs by value (GtkTreeIter new_iter = iter;). You * must free this iter with gtk_tree_iter_free (). - * + * * Return value: a newly allocated copy of @iter. **/ GtkTreeIter * @@ -827,7 +533,7 @@ gtk_tree_iter_copy (GtkTreeIter *iter) /** * gtk_tree_iter_free: * @iter: A dynamically allocated tree iterator. - * + * * Free an iterator that has been allocated on the heap. This function is * mainly used for language bindings. **/ @@ -842,11 +548,11 @@ gtk_tree_iter_free (GtkTreeIter *iter) /** * gtk_tree_model_get_flags: * @tree_model: A #GtkTreeModel. - * + * * Returns a set of flags supported by this interface. The flags are a bitwise * combination of #GtkTreeModelFlags. It is expected that the flags supported * do not change for an interface. - * + * * Return value: The flags supported by this interface. **/ GtkTreeModelFlags @@ -864,9 +570,9 @@ gtk_tree_model_get_flags (GtkTreeModel *tree_model) /** * gtk_tree_model_get_n_columns: * @tree_model: A #GtkTreeModel. - * + * * Returns the number of columns supported by the #tree_model - * + * * Return value: The number of columns. **/ gint @@ -883,9 +589,9 @@ gtk_tree_model_get_n_columns (GtkTreeModel *tree_model) * gtk_tree_model_get_column_type: * @tree_model: A #GtkTreeModel. * @index: The column index. - * + * * Returns the type of the column. - * + * * Return value: The type of the column. **/ GType @@ -905,11 +611,11 @@ gtk_tree_model_get_column_type (GtkTreeModel *tree_model, * @tree_model: A #GtkTreeModel. * @iter: The uninitialized #GtkTreeIter. * @path: The #GtkTreePath. - * + * * Sets @iter to a valid iterator pointing to @path. If the model does not * provide an implementation of this function, it is implemented in terms of * @gtk_tree_model_iter_nth_child. - * + * * Return value: TRUE, if @iter was set. **/ gboolean @@ -951,11 +657,11 @@ gtk_tree_model_get_iter (GtkTreeModel *tree_model, * gtk_tree_model_get_first: * @tree_model: a #GtkTreeModel * @iter: iterator to initialize - * + * * Initialized @iter with the first iterator in the tree (the one at the * root path) and returns %TRUE, or returns %FALSE if there are no * iterable locations in the model (i.e. the tree is empty). - * + * * Return value: %TRUE if @iter was initialized **/ gboolean @@ -964,7 +670,7 @@ gtk_tree_model_get_first (GtkTreeModel *tree_model, { gboolean retval; GtkTreePath *path; - + g_return_val_if_fail (GTK_IS_TREE_MODEL (tree_model), FALSE); g_return_val_if_fail (iter != NULL, FALSE); @@ -981,10 +687,10 @@ gtk_tree_model_get_first (GtkTreeModel *tree_model, * gtk_tree_model_get_path: * @tree_model: A #GtkTreeModel. * @iter: The #GtkTreeIter. - * + * * Returns a newly created #GtkTreePath referenced by @iter. This path should * be freed with #gtk_tree_path_free. - * + * * Return value: a newly created #GtkTreePath. **/ GtkTreePath * @@ -1005,7 +711,7 @@ gtk_tree_model_get_path (GtkTreeModel *tree_model, * @iter: The #GtkTreeIter. * @column: The column to lookup the value at. * @value: An empty #GValue to set. - * + * * Sets initializes and sets @value to that at @column. When done with value, * #g_value_unset needs to be called on it. **/ @@ -1028,10 +734,10 @@ gtk_tree_model_get_value (GtkTreeModel *tree_model, * gtk_tree_model_iter_next: * @tree_model: A #GtkTreeModel. * @iter: The #GtkTreeIter. - * + * * Sets @iter to point to the node following it at the current level. If there * is no next @iter, FALSE is returned and @iter is set to be invalid. - * + * * Return value: TRUE if @iter has been changed to the next node. **/ gboolean @@ -1051,11 +757,11 @@ gtk_tree_model_iter_next (GtkTreeModel *tree_model, * @tree_model: A #GtkTreeModel. * @iter: The new #GtkTreeIter to be set to the child. * @parent: The #GtkTreeIter. - * + * * Sets @iter to point to the first child of @parent. If @parent has no children, * FALSE is returned and @iter is set to be invalid. @parent will remain a valid * node after this function has been called. - * + * * Return value: TRUE, if @child has been set to the first child. **/ gboolean @@ -1075,9 +781,9 @@ gtk_tree_model_iter_children (GtkTreeModel *tree_model, * gtk_tree_model_iter_has_child: * @tree_model: A #GtkTreeModel. * @iter: The #GtkTreeIter to test for children. - * + * * Returns TRUE if @iter has children, FALSE otherwise. - * + * * Return value: TRUE if @iter has children. **/ gboolean @@ -1096,10 +802,10 @@ gtk_tree_model_iter_has_child (GtkTreeModel *tree_model, * gtk_tree_model_iter_n_children: * @tree_model: A #GtkTreeModel. * @iter: The #GtkTreeIter, or NULL. - * + * * Returns the number of children that @iter has. If @iter is NULL, then the * number of toplevel nodes is returned. - * + * * Return value: The number of children of @iter. **/ gint @@ -1119,13 +825,13 @@ gtk_tree_model_iter_n_children (GtkTreeModel *tree_model, * @iter: The #GtkTreeIter to set to the nth child. * @parent: The #GtkTreeIter to get the child from, or NULL. * @n: Then index of the desired child. - * + * * Sets @iter to be the child of @parent, using the given index. The first * index is 0. If the index is too big, or @parent has no children, @iter is * set to an invalid iterator and FALSE is returned. @parent will remain a * valid node after this function has been called. If @parent is NULL, then the * root node is assumed. - * + * * Return value: TRUE, if @parent has an nth child. **/ gboolean @@ -1148,12 +854,12 @@ gtk_tree_model_iter_nth_child (GtkTreeModel *tree_model, * @tree_model: A #GtkTreeModel * @iter: The new #GtkTreeIter to set to the parent. * @child: The #GtkTreeIter. - * + * * Sets @iter to be the parent of @child. If @child is at the toplevel, and * doesn't have a parent, then @iter is set to an invalid iterator and FALSE * is returned. @child will remain a valid node after this function has been * called. - * + * * Return value: TRUE, if @iter is set to the parent of @child. **/ gboolean @@ -1175,7 +881,7 @@ gtk_tree_model_iter_parent (GtkTreeModel *tree_model, * gtk_tree_model_ref_iter: * @tree_model: A #GtkTreeModel. * @iter: The #GtkTreeIter. - * + * * Ref's the iter. This is an optional method for models to implement. To be * more specific, models may ignore this call as it exists primarily for * performance reasons. @@ -1196,7 +902,7 @@ gtk_tree_model_ref_iter (GtkTreeModel *tree_model, * gtk_tree_model_unref_iter: * @tree_model: A #GtkTreeModel. * @iter: The #GtkTreeIter. - * + * * Unref's the iter. This is an optional method for models to implement. To be * more specific, models may ignore this call as it exists primarily for * performance reasons. @@ -1226,7 +932,7 @@ gtk_tree_model_unref_iter (GtkTreeModel *tree_model, * write: gtk_tree_model_set (model, iter, 0, &place_string_here, -1), * where place_string_here is a gchar* to be filled with the string. * If appropriate, the returned values have to be freed or unreferenced. - * + * **/ void gtk_tree_model_get (GtkTreeModel *tree_model, @@ -1250,7 +956,7 @@ gtk_tree_model_get (GtkTreeModel *tree_model, * * See gtk_tree_model_get(), this version takes a va_list for * language bindings to use. - * + * **/ void gtk_tree_model_get_valist (GtkTreeModel *tree_model, @@ -1343,3 +1049,312 @@ gtk_tree_model_deleted (GtkTreeModel *tree_model, g_signal_emit_by_name (tree_model, "deleted", path); } + + +/** + ** GtkTreeRowReference + **/ + +#define ROW_REF_DATA_STRING "gtk-tree-row-refs" + +struct _GtkTreeRowReference +{ + GObject *proxy; + GtkTreeModel *model; + GtkTreePath *path; +}; + +typedef struct +{ + GSList *list; +} RowRefList; + + +static void +release_row_references (gpointer data) +{ + RowRefList *refs = data; + GSList *tmp_list = NULL; + + tmp_list = refs->list; + while (tmp_list != NULL) + { + GtkTreeRowReference *reference = tmp_list->data; + + if (reference->proxy == (GObject *)reference->model) + reference->model = NULL; + reference->proxy = NULL; + + /* we don't free the reference, users are responsible for that. */ + + tmp_list = g_slist_next (tmp_list); + } + + g_slist_free (refs->list); + g_free (refs); +} + +static void +gtk_tree_row_ref_inserted_callback (GObject *object, + GtkTreePath *path, + GtkTreeIter *iter, + gpointer data) +{ + RowRefList *refs = g_object_get_data (data, ROW_REF_DATA_STRING); + + GSList *tmp_list; + + if (refs == NULL) + return; + + /* This function corrects the path stored in the reference to + * account for an insertion. Note that it's called _after_ the insertion + * with the path to the newly-inserted row. Which means that + * the inserted path is in a different "coordinate system" than + * the old path (e.g. if the inserted path was just before the old path, + * then inserted path and old path will be the same, and old path must be + * moved down one). + */ + + tmp_list = refs->list; + + while (tmp_list != NULL) + { + GtkTreeRowReference *reference = tmp_list->data; + + if (reference->path) + { + gint depth = gtk_tree_path_get_depth (path); + gint ref_depth = gtk_tree_path_get_depth (reference->path); + + if (ref_depth >= depth) + { + gint *indices = gtk_tree_path_get_indices (path); + gint *ref_indices = gtk_tree_path_get_indices (reference->path); + gint i; + + /* This is the depth that might affect us. */ + i = depth - 1; + + if (indices[i] <= ref_indices[i]) + ref_indices[i] += 1; + } + } + + tmp_list = g_slist_next (tmp_list); + } +} + +static void +gtk_tree_row_ref_deleted_callback (GObject *object, + GtkTreePath *path, + gpointer data) +{ + RowRefList *refs = g_object_get_data (data, ROW_REF_DATA_STRING); + GSList *tmp_list; + + if (refs == NULL) + return; + + /* This function corrects the path stored in the reference to + * account for an deletion. Note that it's called _after_ the + * deletion with the old path of the just-deleted row. Which means + * that the deleted path is the same now-defunct "coordinate system" + * as the path saved in the reference, which is what we want to fix. + * + * Note that this is different from the situation in "inserted," so + * while you might think you can cut-and-paste between these + * functions, it's not going to work. ;-) + */ + + tmp_list = refs->list; + + while (tmp_list != NULL) + { + GtkTreeRowReference *reference = tmp_list->data; + + if (reference->path) + { + gint depth = gtk_tree_path_get_depth (path); + gint ref_depth = gtk_tree_path_get_depth (reference->path); + + if (ref_depth >= depth) + { + /* Need to adjust path upward */ + gint *indices = gtk_tree_path_get_indices (path); + gint *ref_indices = gtk_tree_path_get_indices (reference->path); + gint i; + + i = depth - 1; + if (indices[i] < ref_indices[i]) + ref_indices[i] -= 1; + else if (indices[i] == ref_indices[i]) + { + /* the referenced node itself, or its parent, was + * deleted, mark invalid + */ + + gtk_tree_path_free (reference->path); + reference->path = NULL; + } + } + + } + tmp_list = g_slist_next (tmp_list); + } +} + +static void +connect_ref_callbacks (GtkTreeModel *model) +{ + g_signal_connect_data (G_OBJECT (model), + "inserted", + (GCallback) gtk_tree_row_ref_inserted_callback, + model, + NULL, + FALSE, + FALSE); + + g_signal_connect_data (G_OBJECT (model), + "deleted", + (GCallback) gtk_tree_row_ref_deleted_callback, + model, + NULL, + FALSE, + FALSE); +} + +static void +disconnect_ref_callbacks (GtkTreeModel *model) +{ + g_signal_handlers_disconnect_matched (G_OBJECT (model), + G_SIGNAL_MATCH_FUNC, + 0, 0, NULL, + gtk_tree_row_ref_inserted_callback, + NULL); + g_signal_handlers_disconnect_matched (G_OBJECT (model), + G_SIGNAL_MATCH_FUNC, + 0, 0, NULL, + gtk_tree_row_ref_deleted_callback, + NULL); +} + +GtkTreeRowReference * +gtk_tree_row_reference_new (GtkTreeModel *model, + GtkTreePath *path) +{ + g_return_val_if_fail (model != NULL, NULL); + g_return_val_if_fail (GTK_IS_TREE_MODEL (model), NULL); + g_return_val_if_fail (path != NULL, NULL); + + return gtk_tree_row_reference_new_proxy (G_OBJECT (model), model, path); +} + +GtkTreeRowReference * +gtk_tree_row_reference_new_proxy (GObject *proxy, + GtkTreeModel *model, + GtkTreePath *path) +{ + GtkTreeRowReference *reference; + RowRefList *refs; + + g_return_val_if_fail (proxy != NULL, NULL); + g_return_val_if_fail (G_IS_OBJECT (proxy), NULL); + g_return_val_if_fail (model != NULL, NULL); + g_return_val_if_fail (GTK_IS_TREE_MODEL (model), NULL); + g_return_val_if_fail (path != NULL, NULL); + + reference = g_new (GtkTreeRowReference, 1); + + reference->proxy = proxy; + reference->model = model; + reference->path = gtk_tree_path_copy (path); + + refs = g_object_get_data (G_OBJECT (proxy), ROW_REF_DATA_STRING); + + if (refs == NULL) + { + refs = g_new (RowRefList, 1); + refs->list = NULL; + + if (model == proxy) + connect_ref_callbacks (model); + + g_object_set_data_full (G_OBJECT (proxy), + ROW_REF_DATA_STRING, + refs, release_row_references); + } + + refs->list = g_slist_prepend (refs->list, reference); + + return reference; +} + +GtkTreePath * +gtk_tree_row_reference_get_path (GtkTreeRowReference *reference) +{ + g_return_val_if_fail (reference != NULL, NULL); + + if (reference->proxy == NULL) + return NULL; + + if (reference->path == NULL) + return NULL; + + return gtk_tree_path_copy (reference->path); +} + +void +gtk_tree_row_reference_free (GtkTreeRowReference *reference) +{ + RowRefList *refs; + + g_return_if_fail (reference != NULL); + + if (reference->proxy) + { + refs = g_object_get_data (G_OBJECT (reference->proxy), ROW_REF_DATA_STRING); + + if (refs == NULL) + { + g_warning (G_STRLOC": bad row reference, proxy has no outstanding row references"); + return; + } + + refs->list = g_slist_remove (refs->list, reference); + + if (refs->list == NULL) + { + disconnect_ref_callbacks (reference->model); + g_object_set_data (G_OBJECT (reference->proxy), + ROW_REF_DATA_STRING, + NULL); + } + } + + if (reference->path) + gtk_tree_path_free (reference->path); + + g_free (reference); +} + +void +gtk_tree_row_reference_inserted (GObject *proxy, + GtkTreePath *path) +{ + g_return_if_fail (proxy != NULL); + g_return_if_fail (G_IS_OBJECT (proxy)); + + gtk_tree_row_ref_inserted_callback (NULL, path, NULL, proxy); + +} + +void +gtk_tree_row_reference_deleted (GObject *proxy, + GtkTreePath *path) +{ + g_return_if_fail (proxy != NULL); + g_return_if_fail (G_IS_OBJECT (proxy)); + + gtk_tree_row_ref_deleted_callback (NULL, path, proxy); +} diff --git a/gtk/gtktreemodel.h b/gtk/gtktreemodel.h index cb3a3b93e0..e72c91efd9 100644 --- a/gtk/gtktreemodel.h +++ b/gtk/gtktreemodel.h @@ -135,69 +135,76 @@ gboolean gtk_tree_path_is_ancestor (GtkTreePath *path, gboolean gtk_tree_path_is_descendant (GtkTreePath *path, GtkTreePath *ancestor); -/* Row reference (an object that tracks model changes so it refers to the - * same row always; a path refers to a position, not a fixed row) +/* Row reference (an object that tracks model changes so it refers to the same + * row always; a path refers to a position, not a fixed row). You almost always + * want to call gtk_tree_row_reference_new. */ -GtkTreeRowReference *gtk_tree_row_reference_new (GtkTreeModel *model, - GtkTreePath *path); -/* returns NULL if the row was deleted or the model was destroyed. */ -GtkTreePath *gtk_tree_row_reference_get_path (GtkTreeRowReference *reference); -void gtk_tree_row_reference_free (GtkTreeRowReference *reference); - - +GtkTreeRowReference *gtk_tree_row_reference_new (GtkTreeModel *model, + GtkTreePath *path); +GtkTreeRowReference *gtk_tree_row_reference_new_proxy (GObject *proxy, + GtkTreeModel *model, + GtkTreePath *path); +GtkTreePath *gtk_tree_row_reference_get_path (GtkTreeRowReference *reference); +void gtk_tree_row_reference_free (GtkTreeRowReference *reference); + +/* These two functions are only needed if you created the row reference with a + * proxy object */ +void gtk_tree_row_reference_inserted (GObject *proxy, + GtkTreePath *path); +void gtk_tree_row_reference_deleted (GObject *proxy, + GtkTreePath *path); + /* GtkTreeIter operations */ -GtkTreeIter *gtk_tree_iter_copy (GtkTreeIter *iter); -void gtk_tree_iter_free (GtkTreeIter *iter); +GtkTreeIter * gtk_tree_iter_copy (GtkTreeIter *iter); +void gtk_tree_iter_free (GtkTreeIter *iter); -GtkType gtk_tree_model_get_type (void) G_GNUC_CONST; -GtkTreeModelFlags gtk_tree_model_get_flags (GtkTreeModel *tree_model); - -/* Column information */ -gint gtk_tree_model_get_n_columns (GtkTreeModel *tree_model); -GType gtk_tree_model_get_column_type (GtkTreeModel *tree_model, - gint index); +GtkType gtk_tree_model_get_type (void) G_GNUC_CONST; +GtkTreeModelFlags gtk_tree_model_get_flags (GtkTreeModel *tree_model); +gint gtk_tree_model_get_n_columns (GtkTreeModel *tree_model); +GType gtk_tree_model_get_column_type (GtkTreeModel *tree_model, + gint index); /* Iterator movement */ -gboolean gtk_tree_model_get_iter (GtkTreeModel *tree_model, - GtkTreeIter *iter, - GtkTreePath *path); -gboolean gtk_tree_model_get_first (GtkTreeModel *tree_model, - GtkTreeIter *iter); -GtkTreePath *gtk_tree_model_get_path (GtkTreeModel *tree_model, - GtkTreeIter *iter); -void gtk_tree_model_get_value (GtkTreeModel *tree_model, - GtkTreeIter *iter, - gint column, - GValue *value); -gboolean gtk_tree_model_iter_next (GtkTreeModel *tree_model, - GtkTreeIter *iter); -gboolean gtk_tree_model_iter_children (GtkTreeModel *tree_model, - GtkTreeIter *iter, - GtkTreeIter *parent); -gboolean gtk_tree_model_iter_has_child (GtkTreeModel *tree_model, - GtkTreeIter *iter); -gint gtk_tree_model_iter_n_children (GtkTreeModel *tree_model, - GtkTreeIter *iter); -gboolean gtk_tree_model_iter_nth_child (GtkTreeModel *tree_model, - GtkTreeIter *iter, - GtkTreeIter *parent, - gint n); -gboolean gtk_tree_model_iter_parent (GtkTreeModel *tree_model, - GtkTreeIter *iter, - GtkTreeIter *child); -void gtk_tree_model_ref_iter (GtkTreeModel *tree_model, - GtkTreeIter *iter); -void gtk_tree_model_unref_iter (GtkTreeModel *tree_model, - GtkTreeIter *iter); - -void gtk_tree_model_get (GtkTreeModel *tree_model, - GtkTreeIter *iter, - ...); -void gtk_tree_model_get_valist (GtkTreeModel *tree_model, - GtkTreeIter *iter, - va_list var_args); +gboolean gtk_tree_model_get_iter (GtkTreeModel *tree_model, + GtkTreeIter *iter, + GtkTreePath *path); +gboolean gtk_tree_model_get_first (GtkTreeModel *tree_model, + GtkTreeIter *iter); +GtkTreePath * gtk_tree_model_get_path (GtkTreeModel *tree_model, + GtkTreeIter *iter); +void gtk_tree_model_get_value (GtkTreeModel *tree_model, + GtkTreeIter *iter, + gint column, + GValue *value); +gboolean gtk_tree_model_iter_next (GtkTreeModel *tree_model, + GtkTreeIter *iter); +gboolean gtk_tree_model_iter_children (GtkTreeModel *tree_model, + GtkTreeIter *iter, + GtkTreeIter *parent); +gboolean gtk_tree_model_iter_has_child (GtkTreeModel *tree_model, + GtkTreeIter *iter); +gint gtk_tree_model_iter_n_children (GtkTreeModel *tree_model, + GtkTreeIter *iter); +gboolean gtk_tree_model_iter_nth_child (GtkTreeModel *tree_model, + GtkTreeIter *iter, + GtkTreeIter *parent, + gint n); +gboolean gtk_tree_model_iter_parent (GtkTreeModel *tree_model, + GtkTreeIter *iter, + GtkTreeIter *child); +void gtk_tree_model_ref_iter (GtkTreeModel *tree_model, + GtkTreeIter *iter); +void gtk_tree_model_unref_iter (GtkTreeModel *tree_model, + GtkTreeIter *iter); +void gtk_tree_model_get (GtkTreeModel *tree_model, + GtkTreeIter *iter, + ...); +void gtk_tree_model_get_valist (GtkTreeModel *tree_model, + GtkTreeIter *iter, + va_list var_args); + /* Signals */ void gtk_tree_model_changed (GtkTreeModel *tree_model, diff --git a/gtk/gtktreeprivate.h b/gtk/gtktreeprivate.h index 74884b4f07..7e2e59ab8f 100644 --- a/gtk/gtktreeprivate.h +++ b/gtk/gtktreeprivate.h @@ -210,11 +210,9 @@ GtkTreeSelection* _gtk_tree_selection_new_with_tree_view (GtkTreeView *tree void _gtk_tree_selection_set_tree_view (GtkTreeSelection *selection, GtkTreeView *tree_view); -GtkTreeRowReference *_gtk_tree_row_reference_new_from_view (GtkTreePath *path); -void _gtk_tree_row_reference_inserted (GtkTreeRowReference *reference, - GtkTreePath *path); -gboolean _gtk_tree_row_reference_deleted (GtkTreeRowReference *reference, - GtkTreePath *path); + + + #ifdef __cplusplus } #endif /* __cplusplus */ diff --git a/gtk/gtktreeselection.c b/gtk/gtktreeselection.c index a63fec367f..5e81a11616 100644 --- a/gtk/gtktreeselection.c +++ b/gtk/gtktreeselection.c @@ -103,10 +103,10 @@ gtk_tree_selection_finalize (GObject *object) /** * _gtk_tree_selection_new: - * + * * Creates a new #GtkTreeSelection object. This function should not be invoked, * as each #GtkTreeView will create it's own #GtkTreeSelection. - * + * * Return value: A newly created #GtkTreeSelection object. **/ GtkTreeSelection* @@ -122,10 +122,10 @@ _gtk_tree_selection_new (void) /** * _gtk_tree_selection_new_with_tree_view: * @tree_view: The #GtkTreeView. - * + * * Creates a new #GtkTreeSelection object. This function should not be invoked, * as each #GtkTreeView will create it's own #GtkTreeSelection. - * + * * Return value: A newly created #GtkTreeSelection object. **/ GtkTreeSelection* @@ -146,7 +146,7 @@ _gtk_tree_selection_new_with_tree_view (GtkTreeView *tree_view) * _gtk_tree_selection_set_tree_view: * @selection: A #GtkTreeSelection. * @tree_view: The #GtkTreeView. - * + * * Sets the #GtkTreeView of @selection. This function should not be invoked, as * it is used internally by #GtkTreeView. **/ @@ -167,7 +167,7 @@ _gtk_tree_selection_set_tree_view (GtkTreeSelection *selection, * gtk_tree_selection_set_mode: * @selection: A #GtkTreeSelection. * @type: The selection type. - * + * * Sets the selection type of the @selection. If the previous type was * #GTK_TREE_SELECTION_MULTI and @type is #GTK_TREE_SELECTION_SINGLE, then * the anchor is kept selected, if it was previously selected. @@ -200,7 +200,7 @@ gtk_tree_selection_set_mode (GtkTreeSelection *selection, anchor_path, &tree, &node); - + if (node && GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED)) selected = TRUE; @@ -225,7 +225,7 @@ gtk_tree_selection_set_mode (GtkTreeSelection *selection, * @func: The selection function. * @data: The selection function's data. * @destroy: The destroy function for user data. May be NULL. - * + * * Sets the selection function. If set, this function is called before any node * is selected or unselected, giving some control over which nodes are selected. **/ @@ -247,9 +247,9 @@ gtk_tree_selection_set_select_function (GtkTreeSelection *selection, /** * gtk_tree_selection_get_user_data: * @selection: A #GtkTreeSelection. - * + * * Returns the user data for the selection function. - * + * * Return value: The user data. **/ gpointer @@ -274,13 +274,13 @@ gtk_tree_selection_get_tree_view (GtkTreeSelection *selection) * @selection: A #GtkTreeSelection. * @model: A pointer set to the #GtkTreeModel, or NULL. * @iter: The #GtkTreeIter, or NULL. - * + * * Sets @iter to the currently selected node if @selection is set to * #GTK_TREE_SELECTION_SINGLE. @iter may be NULL if you just want to test if * @selection has any selected nodes. @model is filled with the current model * as a convenience. This function will not work if you use @selection is * #GTK_TREE_SELECTION_MULTI. - * + * * Return value: TRUE, if there is a selected node. **/ gboolean @@ -292,7 +292,7 @@ gtk_tree_selection_get_selected (GtkTreeSelection *selection, GtkRBNode *node; GtkTreePath *anchor_path; gboolean retval; - + g_return_val_if_fail (selection != NULL, FALSE); g_return_val_if_fail (GTK_IS_TREE_SELECTION (selection), FALSE); g_return_val_if_fail (selection->type == GTK_TREE_SELECTION_SINGLE, FALSE); @@ -301,7 +301,7 @@ gtk_tree_selection_get_selected (GtkTreeSelection *selection, if (model) *model = selection->tree_view->priv->model; - + if (selection->tree_view->priv->anchor == NULL) return FALSE; @@ -309,7 +309,7 @@ gtk_tree_selection_get_selected (GtkTreeSelection *selection, if (anchor_path == NULL) return FALSE; - + if (iter == NULL) { gtk_tree_path_free (anchor_path); @@ -317,7 +317,7 @@ gtk_tree_selection_get_selected (GtkTreeSelection *selection, } retval = FALSE; - + if (!_gtk_tree_view_find_node (selection->tree_view, anchor_path, &tree, @@ -336,7 +336,7 @@ gtk_tree_selection_get_selected (GtkTreeSelection *selection, } gtk_tree_path_free (anchor_path); - + return retval; } @@ -345,7 +345,7 @@ gtk_tree_selection_get_selected (GtkTreeSelection *selection, * @selection: A #GtkTreeSelection. * @func: The function to call for each selected node. * @data: user data to pass to the function. - * + * * Calls a function for each selected node. **/ void @@ -442,7 +442,7 @@ gtk_tree_selection_selected_foreach (GtkTreeSelection *selection, * gtk_tree_selection_select_path: * @selection: A #GtkTreeSelection. * @path: The #GtkTreePath to be selected. - * + * * Select the row at @path. **/ void @@ -480,7 +480,7 @@ gtk_tree_selection_select_path (GtkTreeSelection *selection, * gtk_tree_selection_unselect_path: * @selection: A #GtkTreeSelection. * @path: The #GtkTreePath to be unselected. - * + * * Unselects the row at @path. **/ void @@ -514,7 +514,7 @@ gtk_tree_selection_unselect_path (GtkTreeSelection *selection, * gtk_tree_selection_select_iter: * @selection: A #GtkTreeSelection. * @iter: The #GtkTreeIter to be selected. - * + * * Selects the specified iterator. **/ void @@ -544,7 +544,7 @@ gtk_tree_selection_select_iter (GtkTreeSelection *selection, * gtk_tree_selection_unselect_iter: * @selection: A #GtkTreeSelection. * @iter: The #GtkTreeIter to be unselected. - * + * * Unselects the specified iterator. **/ void @@ -612,7 +612,7 @@ gtk_tree_selection_real_select_all (GtkTreeSelection *selection) gint dirty; /* Just select the last row */ - + dirty = gtk_tree_selection_real_unselect_all (selection); tree = selection->tree_view->priv->tree; @@ -638,7 +638,7 @@ gtk_tree_selection_real_select_all (GtkTreeSelection *selection) else { /* Mark all nodes selected */ - + tuple = g_new (struct _TempTuple, 1); tuple->selection = selection; tuple->dirty = FALSE; @@ -661,7 +661,7 @@ gtk_tree_selection_real_select_all (GtkTreeSelection *selection) /** * gtk_tree_selection_select_all: * @selection: A #GtkTreeSelection. - * + * * Selects all the nodes. If the type of @selection is * #GTK_TREE_SELECTION_SINGLE, then the last row is selected. **/ @@ -706,7 +706,7 @@ gtk_tree_selection_real_unselect_all (GtkTreeSelection *selection) GtkRBTree *tree = NULL; GtkRBNode *node = NULL; GtkTreePath *anchor_path; - + if (selection->tree_view->priv->anchor == NULL) return FALSE; @@ -714,7 +714,7 @@ gtk_tree_selection_real_unselect_all (GtkTreeSelection *selection) if (anchor_path == NULL) return FALSE; - + _gtk_tree_view_find_node (selection->tree_view, anchor_path, &tree, @@ -724,7 +724,7 @@ gtk_tree_selection_real_unselect_all (GtkTreeSelection *selection) if (tree == NULL) return FALSE; - + if (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED)) { if (gtk_tree_selection_real_select_node (selection, tree, node, FALSE)) @@ -737,17 +737,17 @@ gtk_tree_selection_real_unselect_all (GtkTreeSelection *selection) return FALSE; } else - { + { tuple = g_new (struct _TempTuple, 1); tuple->selection = selection; tuple->dirty = FALSE; - + _gtk_rbtree_traverse (selection->tree_view->priv->tree, selection->tree_view->priv->tree->root, G_PRE_ORDER, unselect_all_helper, tuple); - + if (tuple->dirty) { g_free (tuple); @@ -761,7 +761,7 @@ gtk_tree_selection_real_unselect_all (GtkTreeSelection *selection) /** * gtk_tree_selection_unselect_all: * @selection: A #GtkTreeSelection. - * + * * Unselects all the nodes. **/ void @@ -873,7 +873,7 @@ gtk_tree_selection_real_select_range (GtkTreeSelection *selection, * @selection: A #GtkTreeSelection. * @start_path: The initial node of the range. * @end_path: The final node of the range. - * + * * Selects a range of nodes, determined by @start_path and @end_path inclusive. **/ void @@ -931,7 +931,7 @@ _gtk_tree_selection_internal_select_node (GtkTreeSelection *selection, if (gtk_tree_selection_real_select_node (selection, tree, node, TRUE)) { selection->tree_view->priv->anchor = - gtk_tree_row_reference_new (selection->tree_view->priv->model, path); + gtk_tree_row_reference_new_proxy (G_OBJECT (selection->tree_view), selection->tree_view->priv->model, path); } } } @@ -941,7 +941,7 @@ _gtk_tree_selection_internal_select_node (GtkTreeSelection *selection, { dirty = TRUE; selection->tree_view->priv->anchor = - gtk_tree_row_reference_new (selection->tree_view->priv->model, path); + gtk_tree_row_reference_new_proxy (G_OBJECT (selection->tree_view), selection->tree_view->priv->model, path); } } } @@ -952,10 +952,9 @@ _gtk_tree_selection_internal_select_node (GtkTreeSelection *selection, { if (selection->tree_view->priv->anchor) gtk_tree_row_reference_free (selection->tree_view->priv->anchor); - + selection->tree_view->priv->anchor = - gtk_tree_row_reference_new (selection->tree_view->priv->model, - path); + gtk_tree_row_reference_new_proxy (G_OBJECT (selection->tree_view), selection->tree_view->priv->model, path); dirty = gtk_tree_selection_real_select_node (selection, tree, node, TRUE); } else if ((state & (GDK_CONTROL_MASK|GDK_SHIFT_MASK)) == (GDK_SHIFT_MASK|GDK_CONTROL_MASK)) @@ -969,10 +968,9 @@ _gtk_tree_selection_internal_select_node (GtkTreeSelection *selection, flags = node->flags; if (selection->tree_view->priv->anchor) gtk_tree_row_reference_free (selection->tree_view->priv->anchor); - + selection->tree_view->priv->anchor = - gtk_tree_row_reference_new (selection->tree_view->priv->model, - path); + gtk_tree_row_reference_new_proxy (G_OBJECT (selection->tree_view), selection->tree_view->priv->model, path); if ((flags & GTK_RBNODE_IS_SELECTED) == GTK_RBNODE_IS_SELECTED) dirty |= gtk_tree_selection_real_select_node (selection, tree, node, FALSE); @@ -992,18 +990,17 @@ _gtk_tree_selection_internal_select_node (GtkTreeSelection *selection, if (selection->tree_view->priv->anchor) gtk_tree_row_reference_free (selection->tree_view->priv->anchor); - + selection->tree_view->priv->anchor = - gtk_tree_row_reference_new (selection->tree_view->priv->model, - path); - + gtk_tree_row_reference_new_proxy (G_OBJECT (selection->tree_view), selection->tree_view->priv->model, path); + dirty |= gtk_tree_selection_real_select_node (selection, tree, node, TRUE); } } if (anchor_path) gtk_tree_path_free (anchor_path); - + if (dirty) gtk_signal_emit (GTK_OBJECT (selection), tree_selection_signals[SELECTION_CHANGED]); } @@ -1038,7 +1035,7 @@ gtk_tree_selection_real_select_node (GtkTreeSelection *selection, selected = TRUE; gtk_tree_path_free (path); } - + if (selected == TRUE) { node->flags ^= GTK_RBNODE_IS_SELECTED; diff --git a/gtk/gtktreeview.c b/gtk/gtktreeview.c index b5c0d5a64c..fed2bd1098 100644 --- a/gtk/gtktreeview.c +++ b/gtk/gtktreeview.c @@ -2184,8 +2184,7 @@ gtk_tree_view_focus (GtkContainer *container, gtk_tree_row_reference_free (tree_view->priv->cursor); tree_view->priv->cursor = - gtk_tree_row_reference_new (tree_view->priv->model, - tmp_path); + gtk_tree_row_reference_new_proxy (G_OBJECT (tree_view), tree_view->priv->model, tmp_path); cursor_path = tmp_path; } @@ -2231,8 +2230,7 @@ gtk_tree_view_focus (GtkContainer *container, gtk_tree_row_reference_free (tree_view->priv->cursor); tree_view->priv->cursor = - gtk_tree_row_reference_new (tree_view->priv->model, - tmp_path); + gtk_tree_row_reference_new_proxy (G_OBJECT (tree_view), tree_view->priv->model, tmp_path); cursor_path = tmp_path; } @@ -2262,8 +2260,7 @@ gtk_tree_view_focus (GtkContainer *container, gtk_tree_row_reference_free (tree_view->priv->cursor); tree_view->priv->cursor = - gtk_tree_row_reference_new (tree_view->priv->model, - tmp_path); + gtk_tree_row_reference_new_proxy (G_OBJECT (tree_view), tree_view->priv->model, tmp_path); cursor_path = tmp_path; gtk_tree_selection_select_path (tree_view->priv->selection, @@ -2364,8 +2361,7 @@ gtk_tree_view_focus (GtkContainer *container, cursor_path, state); - tree_view->priv->cursor = gtk_tree_row_reference_new (tree_view->priv->model, - cursor_path); + tree_view->priv->cursor = gtk_tree_row_reference_new_proxy (G_OBJECT (tree_view), tree_view->priv->model, cursor_path); /* draw the newly-selected row */ @@ -2547,6 +2543,9 @@ gtk_tree_view_inserted (GtkTreeModel *model, } else if (iter == NULL) gtk_tree_model_get_iter (model, iter, path); + + /* Update all row-references */ + gtk_tree_row_reference_inserted (G_OBJECT (data), path); depth = gtk_tree_path_get_depth (path); indices = gtk_tree_path_get_indices (path); @@ -2704,7 +2703,9 @@ gtk_tree_view_deleted (GtkTreeModel *model, if (tree == NULL) return; - + + gtk_tree_row_reference_deleted (G_OBJECT (data), path); + /* next, update the selection */ if (tree_view->priv->anchor) { @@ -5383,8 +5384,7 @@ gtk_tree_view_set_drag_dest_row (GtkTreeView *tree_view, if (path) { tree_view->priv->drag_dest_row = - gtk_tree_row_reference_new (tree_view->priv->model, - path); + gtk_tree_row_reference_new_proxy (G_OBJECT (tree_view), tree_view->priv->model, path); gtk_tree_view_queue_draw_path (tree_view, path, NULL); } else -- 2.30.2